﻿using System.Linq;
using LM.InterfacesFabricas.Interfaces.Repositorios;
using LM.Negocio.Objetos;

namespace LM.Negocio.Validadores
{
    using System;

    using LM.InterfacesFabricas.Basicos.Enumeradores;

    public class ValidadorDeLocacao : ValidadorAbastrato
    {
        private Locacao _objetoValidado;

        private IRepositorioDeConsultaDeObjetos<Locacao> _repositorio;

        private IRepositorioDeConsultaDeObjetos<Veiculo> _repositorioDeVeiculo;

        private IRepositorioDeConsultaDeObjetos<Vaga> _repositorioDeVaga;

        private IRepositorioDeConsultaDeObjetos<Cliente> _repositorioDeCliente;

        private IRepositorioDeConsultaDeObjetos<Dependente> _repositorioDeDependente;

        private IRepositorioDeConsultaDeObjetos<TabelaPreco> _repositorioDeTabelaPreco;

        public ValidadorDeLocacao(
            IRepositorioDeConsultaDeObjetos<Locacao> repositorioDeLocacao,
            IRepositorioDeConsultaDeObjetos<Veiculo> repositorioDeVeiculo,
            IRepositorioDeConsultaDeObjetos<Vaga> repositorioDeVaga,
            IRepositorioDeConsultaDeObjetos<Cliente> repositorioDeCliente,
            IRepositorioDeConsultaDeObjetos<Dependente> repositorioDeDependente,
            IRepositorioDeConsultaDeObjetos<TabelaPreco> repositorioDeTabelaPreco)
        {
            if (repositorioDeLocacao == null)
            {
                throw new ArgumentNullException("repositorioDeLocacao");
            }

            _repositorio = repositorioDeLocacao;
            _repositorioDeCliente = repositorioDeCliente;
            _repositorioDeDependente = repositorioDeDependente;
            _repositorioDeTabelaPreco = repositorioDeTabelaPreco;
            _repositorioDeVaga = repositorioDeVaga;
            _repositorioDeVeiculo = repositorioDeVeiculo;
        }

        public void ValidaGragacao(Locacao locacao)
        {
            if (locacao == null)
            {
                throw new ArgumentException("locacao");
            }

            _objetoValidado = locacao;
            base.LimpeInconsistencias();

            base.GarantaSucesso();
        }

        public void ValidaAtualizacao(Locacao locacao)
        {
            if (locacao == null)
            {
                throw new ArgumentException("locacao");
            }

            _objetoValidado = locacao;
            base.LimpeInconsistencias();

            base.GarantaSucesso();
        }

        public void ValidaExclusao(Locacao locacao)
        {
            if (locacao == null)
            {
                throw new ArgumentException("locacao");
            }

            _objetoValidado = locacao;
            base.LimpeInconsistencias();

            base.GarantaSucesso();
        }

        public void ValidaCodigodoNaoInformado()
        {
            if (_objetoValidado.Codigo < 1)
            {
                AdicioneInconsistencia("Código da locação não foi informada.");
            }
        }

        public void ValidaDataEntradadoNaoInformada()
        {
            if (_objetoValidado.DataEntrada == null)
            {
                AdicioneInconsistencia("Data de entrada não foi informada.");
            }
        }

        public void ValidaDataSaidadoNaoInformada()
        {
            if (_objetoValidado.DataSaida == null)
            {
                AdicioneInconsistencia("Data de saída não foi informada.");
            }
        }

        public void ValidaDatasEntradaSaida()
        {
            if (_objetoValidado.DataEntrada > _objetoValidado.DataSaida)
            {
                AdicioneInconsistencia("Data de saída não pode ser menor que a data de entrada.");
            }
        }

        public void ValidaStatusNaoInformado()
        {
            if (Enum.IsDefined(typeof(EnumStatus), _objetoValidado.Status))
            {
                AdicioneInconsistencia("Status não informado ou status não é válido.");
            }
        }

        public void ValidaVeiculoNaoInformado()
        {
            if (_objetoValidado.Veiculo == null)
            {
                AdicioneInconsistencia("Veículo não informado.");
            }
        }

        public void ValidaClienteNaoInformado()
        {
            if (_objetoValidado.Cliente == null)
            {
                AdicioneInconsistencia("Cliente não informado.");
            }
        }

        public void ValidaVagaNaoInformado()
        {
            if (_objetoValidado.Vaga == null)
            {
                AdicioneInconsistencia("Vaga não informada.");
            }
        }

        public void ValidaTabelaDePrecoNaoInformado()
        {
            if (_objetoValidado.TabelaPreco == null)
            {
                AdicioneInconsistencia("Tabela de precos não informado.");
            }
        }

        #region Validação dos objetos referenciados

        public void ValidaVeiculoNaoCadastrado()
        {
            var veiculo = _repositorioDeVeiculo.Consulte(v => v.Codigo == _objetoValidado.Veiculo.Codigo);
            if (veiculo == null)
            {
                AdicioneInconsistencia("Veículo não cadastrado.");
            }
        }

        public void ValidaVagaNaoCadastrada()
        {
            var vaga = _repositorioDeVaga.Consulte(v => v.Codigo == _objetoValidado.Vaga.Codigo);
            if (vaga == null)
            {
                AdicioneInconsistencia("Vaga não cadastrado.");
            }
        }

        public void ValidaClienteNaoCadastrado()
        {
            var cliente = _repositorioDeCliente.Consulte(v => v.Codigo == _objetoValidado.Cliente.Codigo).FirstOrDefault();
            if (cliente == null)
            {
                AdicioneInconsistencia("Cliente não cadastrado.");
            }
        }

        public void ValidaDependenteNaoCadastrado()
        {
            if (_objetoValidado.Dependente != null)
            {
                var dependente = _repositorioDeDependente.Consulte(v => v.Codigo == _objetoValidado.Dependente.Codigo).FirstOrDefault();
                if (dependente == null)
                {
                    AdicioneInconsistencia("Dependente não cadastrado.");
                }
            }
        }

        public void ValidaDependenteNaoPertenceAoCliente()
        {
            if (_objetoValidado.Dependente != null)
            {
                var cliente = _repositorioDeCliente.Consulte(v => v.Codigo == _objetoValidado.Cliente.Codigo).FirstOrDefault();
                var dependente = _repositorioDeDependente.Consulte(v => v.Codigo == _objetoValidado.Dependente.Codigo).FirstOrDefault();
                if (cliente != null && dependente != null)
                {
                    if (!cliente.Dependentes.Contains(dependente))
                    {
                        AdicioneInconsistencia("Dependente não relacionado ao Cliente informado.");
                    }
                }
            }
        }

        #endregion
    }
}
